﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using NUnit.Framework;

namespace Domain.Test
{
	[TestFixture]
	public class TestProgram
	{
		[Test]
		public void ClickingAButton_ThatA_ShouldB()
		{
			var program = new GrandCentral(new RuleRepo());
			var btn = new InputButton();

			var listener = new Listener();

			program.When(btn.Is_Pressed).Then(listener.Should_Toggle);

			Assert.That(listener.State.IsOff);

			btn.Press();

			Assert.That(listener.State.IsOn);
		}

		[Test]
		public void SettingUpARule_ShouldSaveItToTheRepo()
		{
			IRuleRepo repo = new RuleRepo();
			var program = new GrandCentral(repo);

			program.When(new InputButton().Is_Pressed).Then(new Listener().Should_Toggle);

			Assert.That(repo.All().Count(),Is.EqualTo(1));
		}

	}

	public interface IRuleRepo
	{
		IEnumerable<IRule> All();

		void Add(IRule rule);
	}

	public class RuleRepo : IRuleRepo
	{
		private IList<IRule> _rules=new List<IRule>();

		public IEnumerable<IRule> All()
		{
			return new ReadOnlyCollection<IRule>(_rules);
		}

		public void Add(IRule rule)
		{
			_rules.Add(rule);
		}
	}

	#region move
	public class Listener : IShould
	{
		public State State { get; private set; }

		public Listener()
		{
			State = new State();
		}
		
		public IShould Should_Toggle
		{
			get { return this; }
			
		}


		public void Execute()
		{
			State.Status = !State.Status;
		}
	}

	public class State : IState
	{

		public bool Status { get; set; }

		public bool IsOff { get { return !Status; } }
		public bool IsOn { get { return Status; } }
	}

	public delegate void HappenedEventHandler(object sender, EventArgs e);

	public interface IState
	{
		bool IsOff { get;}
		bool IsOn { get; }
	}

	public class InputButton : ISomethingThatCanBeDone
	{
		public void Press()
		{
			if(Happened!=null)Happened(this,new EventArgs());
		}

		public ISomethingThatCanBeDone Is_Pressed
		{
			get { return this; } 
		}

		public event HappenedEventHandler Happened;
	}
	
	public class GrandCentral
	{
		private readonly IRuleRepo _repo;

		public GrandCentral(IRuleRepo repo)
		{
			_repo = repo;
		}

		public IEnumerable<IRule> Rules { get; private set; }

		public IWhen When(ISomethingThatCanBeDone somethingThatCanBeDone)
		{
			
			var when =  new When(somethingThatCanBeDone);
			_repo.Add(new GrandCentralRule());
			return when;
		}
	}

	public class GrandCentralRule : IRule
	{
	}


	public interface IRule
	{
	}

	public class When : IWhen
	{
		private readonly ISomethingThatCanBeDone _somethingThatCanBeDone;

		public When(ISomethingThatCanBeDone somethingThatCanBeDone)
		{
			_somethingThatCanBeDone = somethingThatCanBeDone;
		}


		public void Then(IShould listener)
		{
			_somethingThatCanBeDone.Happened += delegate
				                                    {
														listener.Execute();
				                                    };
		}
	}

	public interface IWhen 
	{
		void Then(IShould listener);
	}

	public interface IThen
	{
		void Toggle();
		void Should(object execute);
	}

	public interface ISomethingThatCanBeDone
	{
		 event HappenedEventHandler Happened;
	}

	public interface IShould
	{
		void Execute();
	}

	#endregion
}
